import { _decorator, Camera, instantiate, Prefab, Node, Component, Collider, ITriggerEvent } from "cc";
const { ccclass, property } = _decorator;
import { IArea, ICountry, ITroop } from "../../shared/gameClient/games/OccupationTheWarModels";
import { LinkMainNodeComponent } from "../common/LinkMainNodeComponent";
import { NodeRecycleMode, NodeRecyclePool } from "../common/NodeRecyclePool";
import { OTWAreaComponent } from "./Components/OTWAreaComponent";
import { OTWFlagComponent } from "./Components/OTWFlagComponent";
import { OTWObjectComponent } from "./Components/OTWObjectComponent";
import { OTWTroopComponent } from "./Components/OTWTroopComponent";
import { OTWTroopFlagComponent } from "./Components/OTWTroopFlagComponent";
import { OTWTroopRenderComponent } from "./Components/OTWTroopRenderComponent";
import { OTWAreaData } from "./Data/OTWAreaData";
import { OTWGameData } from "./Data/OTWGameData";
import { OTWTroopData } from "./Data/OTWTroopData";
import { OTWGameResource } from "./OTWGameResource";
import { OTWSceneManager } from "./OTWSceneManager";


@ccclass('OTWTroopManager')
export class OTWTroopManager extends Component {

    private troopColliderPool: NodeRecyclePool = new NodeRecyclePool(NodeRecycleMode.Active);
    private troopRenderPool: NodeRecyclePool = new NodeRecyclePool(NodeRecycleMode.Active);
    private troopFlagPool: NodeRecyclePool = new NodeRecyclePool(NodeRecycleMode.Active);

    private static TroopIncId = 0;

    @property(OTWSceneManager)
    public SceneMgr!: OTWSceneManager;
    @property(OTWGameResource)
    public GameRes!: OTWGameResource;

    public getGameData!: () => OTWGameData;
    private onTriggerEnterHandler = (event: ITriggerEvent) => { this.onTriggerEnter(event) };

    /**某个国家失败了触发(该国家没有任何地块以及没任何士兵时触发)*/
    public onCountryLose: ((country: ICountry) => void) | null = null;

    private createTroopCollider(troop: ITroop): Node {
        var node = this.troopColliderPool.reuseOne();
        if (!node) {
            node = instantiate(this.GameRes.TroopColliderPrefab!);
        }
        node.name = "TroopCollider_" + troop.troopId;
        node.setPosition(troop.x, 0, troop.z);
        this.SceneMgr.GameObjContainer!.addChild(node);
        return node!;
    }
    private createTroopRender(troop: ITroop): Node {
        var node = this.troopRenderPool.reuseOne();
        if (!node) {
            node = instantiate(this.GameRes.TroopRenderPrefab!);
        }
        node.name = "TroopRender_" + troop.troopId;
        node.setPosition(troop.x, 0, troop.z);
        this.SceneMgr.GameObjContainer!.addChild(node);
        return node!;
    }
    private createTroopFlag(troop: ITroop, country: ICountry | null, renderNode: Node): Node {
        var node = this.troopFlagPool.reuseOne();
        if (node) {
            //存在,则重新初始化节点组件数据
            OTWFlagComponent.initFlagNode(OTWTroopFlagComponent, node,
                this.getGameData, this.GameRes.TroopFlagPrefab!, renderNode,
                this.SceneMgr.MainCamera!, country);
        } else {
            //不存在则新建一个
            node = OTWFlagComponent.createFlagNode(OTWTroopFlagComponent,
                this.getGameData, this.GameRes.TroopFlagPrefab!, renderNode,
                this.SceneMgr.MainCamera!, country);
        }
        node.name = "TroopFlag_" + troop.troopId;
        node.setPosition(troop.x, 0, troop.z);
        this.SceneMgr.GameObjFlagUI!.addChild(node);
        return node!;
    }

    private buildTroop(fromArea: IArea, toArea: IArea, troopsCount: number): ITroop {
        return {
            troopId: (++OTWTroopManager.TroopIncId).toString(),
            countryId: fromArea.countryId!,
            fromAreaIndex: fromArea.areaIndex,
            toAreaIndex: toArea.areaIndex,
            troopsCount: troopsCount,
            x: fromArea.x,
            z: fromArea.z,
        };
    }

    /**
     * 创建士兵, 销毁请使用 destroyTroop 方法
     * @param fromArea 
     * @param toArea 
     * @returns 
     */
    public createTroopData(troop: ITroop, fromArea: IArea, toArea: IArea, country: ICountry | null): OTWTroopData {
        var renderNode = this.createTroopRender(troop);
        var colliderNode = this.createTroopCollider(troop);
        var flagNode = this.createTroopFlag(troop, country, renderNode);
        var renderComp = renderNode.getComponent(OTWTroopRenderComponent)!;
        var troopComp = colliderNode.getComponent(OTWTroopComponent)!;
        var flagComp = flagNode.getComponent(OTWTroopFlagComponent)!;

        var troopData: OTWTroopData = {
            troop: troop,
            fromArea: fromArea,
            toArea: toArea,
            country: country,
            renderNode: renderNode,
            renderComp: renderComp,
            troopNode: colliderNode,
            troopComp: troopComp,
            flagNode: flagNode,
            flagComp: flagComp,
        };

        renderComp.troopData = troopData;
        renderComp.getGameData = this.getGameData;

        flagComp.troopData = troopData;
        flagComp.getGameData = this.getGameData;
        flagComp.updateShow();

        troopComp.troopData = troopData;
        troopComp.getGameData = this.getGameData;
        troopComp.setMove(troopData.toArea.x, troopData.toArea.z);

        var collider = colliderNode.getComponentInChildren(Collider);
        collider?.on('onTriggerEnter', this.onTriggerEnterHandler);

        this.getGameData().map!.allAttackingTroop[troop.troopId] = troop;
        this.getGameData().allAttackingTroopData[troop.troopId] = troopData;

        return troopData;
    }


    /**
     * 数据还原士兵, 销毁请使用 destroyTroop 方法,全新创建请使用 createTroop
     * @param fromArea 
     * @param toArea 
     * @returns 
     */
    public restoreTroop(troop: ITroop): OTWTroopData {
        var fromArea = this.getGameData().map!.allArea[troop.fromAreaIndex];
        var toArea = this.getGameData().map!.allArea[troop.toAreaIndex];
        var country = troop.countryId ? this.getGameData().map!.allCountry[troop.countryId] : null;
        return this.createTroopData(troop, fromArea, toArea, country);
    }

    /**
     * 创建士兵, 销毁请使用 destroyTroop 方法
     * @param fromArea 
     * @param toArea 
     * @returns 
     */
    public createTroop(fromArea: IArea, toArea: IArea, troopsCount: number): OTWTroopData {
        var troop = this.buildTroop(fromArea, toArea, troopsCount);
        var country = fromArea.countryId ? this.getGameData().map!.allCountry[fromArea.countryId] : null;
        return this.createTroopData(troop, fromArea, toArea, country);
    }


    /**
     * 销毁士兵
     * @date 2022/3/22 - 下午1:52:13
     *
     * @public
     * @param {OTWTroopData} troopData
     */
    public destroyTroop(troopData: OTWTroopData) {
        troopData.renderComp.troopData = null;
        troopData.flagComp.troopData = null;
        troopData.troopComp.troopData = null;

        this.troopColliderPool.recycle(troopData.troopNode);
        this.troopRenderPool.recycle(troopData.renderNode);
        this.troopFlagPool.recycle(troopData.flagNode);

        delete this.getGameData().map!.allAttackingTroop[troopData.troop.troopId];
        delete this.getGameData().allAttackingTroopData[troopData.troop.troopId];

        var collider = troopData.troopNode.getComponentInChildren(Collider);
        collider?.off('onTriggerEnter', this.onTriggerEnterHandler);
    }


    private onTriggerEnter(event: ITriggerEvent) {
        var self = event.selfCollider.getComponent(LinkMainNodeComponent)?.MainNode?.getComponent(OTWTroopComponent);
        var other = event.otherCollider.getComponent(LinkMainNodeComponent)?.MainNode?.getComponent(OTWObjectComponent);
        var troopData = self?.troopData;
        if (self && other && troopData) {
            switch (other.objType?.call(other)) {
                case "Area":
                    return this.onCollisionArea(troopData, (other as OTWAreaComponent).areaData);
                case "Troop":
                    return this.onCollisionTroop(troopData, (other as OTWTroopComponent).troopData);
            }
        }
    }
    private onCollisionArea(troopData: OTWTroopData, areaData: OTWAreaData | null) {
        if (!areaData) return;

        //如果是出发地块的碰撞,则忽略
        if (troopData.troop.fromAreaIndex == areaData.area.areaIndex) return;

        //如果是同个国家,则为兵力转移
        if (areaData.country?.countryId === troopData.country?.countryId) {

            //只有是目标地块才转移, 不然忽略
            if (troopData.toArea.areaIndex == areaData.area.areaIndex) {
                areaData.area.troopsCurr += troopData.troop.troopsCount;
                areaData.area.troopsCurrCalculate += troopData.troop.troopsCount;
                areaData.flagComp.updateShow();

                troopData.troop.troopsCount = 0;
                this.destroyTroop(troopData);
            }

            return;
        }

        //不同国家则为攻击
        if (areaData.area.troopsCurr < troopData.troop.troopsCount) {
            //剩余兵力不够,被攻打下来,转移所属国家
            areaData.area.troopsCurrCalculate
                = areaData.area.troopsCurr
                = troopData.troop.troopsCount - areaData.area.troopsCurr;

            var loseCountry = areaData.country;
            areaData.country = troopData.country;
            areaData.area.countryId = troopData.country ? troopData.country.countryId : null;
            areaData.flagComp.country = troopData.country;

            if (loseCountry) {
                //判断失败的地块所处国家,是否还有其他地块,没了则失败
                if (!this.getGameData().map?.allArea.find(a => a.countryId === loseCountry!.countryId)) {
                    this.onCountryLose?.call(this, loseCountry);
                }
            }

        } else {
            //剩余兵力足够,只消耗兵力即可
            areaData.area.troopsCurr -= troopData.troop.troopsCount;
            areaData.area.troopsCurrCalculate -= troopData.troop.troopsCount;
        }
        areaData.flagComp.updateShow();
        troopData.troop.troopsCount = 0;
        this.destroyTroop(troopData);

        //todo:销毁时播放攻击动画,然后删除对应兵力,标记销毁, 动画播放完后再实际销毁
    }
    private onCollisionTroop(troopData: OTWTroopData, otherTroopData: OTWTroopData | null) {
        if (!otherTroopData) return;

        //如果是同个国家,则忽略
        if (troopData.country?.countryId === otherTroopData.country?.countryId) {
            return;
        }

        //不同国家则为攻击
        if (troopData.troop.troopsCount === otherTroopData.troop.troopsCount) {
            //如果兵力相等,对消
            troopData.troop.troopsCount = 0;
            this.destroyTroop(troopData);
            otherTroopData.troop.troopsCount = 0;
            this.destroyTroop(otherTroopData);
        } else {
            var winnerData = troopData.troop.troopsCount > otherTroopData.troop.troopsCount
                ? troopData : otherTroopData;
            var loserData = troopData.troop.troopsCount > otherTroopData.troop.troopsCount
                ? otherTroopData : troopData;

            winnerData.troop.troopsCount -= loserData.troop.troopsCount;
            winnerData.flagComp.updateShow();
            loserData.troop.troopsCount = 0;
            this.destroyTroop(loserData);
        }


        //todo:开始播放攻击动画,然后删除对应兵力,先简单删除和销毁
    }

}